/*******************************************************************************
 * Copyright (c) 2011 - 2012 TXT e-solutions SpA
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * This work was performed within the IoT_at_Work Project
 * and partially funded by the European Commission's
 * 7th Framework Programme under the research area ICT-2009.1.3
 * Internet of Things and enterprise environments.
 *
 *
 * Authors:
 *     Cristoforo Seccia (TXT e-solutions SpA)
 *     Salvatore Piccione (TXT e-solutions SpA - salvatore.piccione AT network.txtgroup.com)
 *
 * Contributors:
 *      Domenico Rotondi (TXT e-solutions SpA)
 *******************************************************************************/
package it.txt.access.capability.revocation.wizard.panel.controller;

import it.txt.access.capability.commons.identifier.IdentifierGenerator;
import it.txt.access.capability.commons.utils.CalendarUtils;
import it.txt.access.capability.revocation.CapabilityRevocationType;
import it.txt.access.capability.revocation.CapabilityRevocationType.ReturnReceiptTo;
import it.txt.access.capability.revocation.CapabilityRevocationType.RevokedCapabilityData;
import it.txt.access.capability.revocation.CapabilityRevocationType.RevokedCapabilityData.DependentTreeEffects;
import it.txt.access.capability.revocation.wizard.Wizard;
import it.txt.access.capability.revocation.wizard.WizardPanelController;
import it.txt.access.capability.revocation.wizard.panel.PanelRevocationData;
import it.txt.access.capability.revocation.wizard.panel.exception.PanelRevocationDataException;
import it.txt.access.capability.revocation.wizard.panel.objects.AuthorisingCapabilitySelectionResult;
import it.txt.access.capability.revocation.wizard.panel.objects.RevocationDataInsertionResultObject;
import it.txt.access.capability.revocation.ObjectFactory;
import it.txt.access.capability.revocation.RevokedCapabilityIdentifierType;

import java.awt.Component;
import java.security.NoSuchAlgorithmException;
import java.util.Date;
import java.util.ResourceBundle;

import javax.swing.JOptionPane;
import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.XMLGregorianCalendar;

import oasis.names.tc.saml._2_0.assertion.NameIDType;

/**
 *
 * @author Cristoforo Seccia (TXT e-solutions SpA)
 * @author Salvatore Piccione (TXT e-solutions SpA - salvatore.piccione AT network.txtgroup.com)
 */
public class ControllerPanelRevocationData extends WizardPanelController {

    private PanelRevocationData panel;
    private final int completedPercentage;
    private RevocationDataInsertionResultObject forwardObject;
    
    public ControllerPanelRevocationData(Wizard wizard, int completedPercentage, String title) {
        super(wizard);
        panel = new PanelRevocationData(title, getWizard(), this);
        Date today = new Date();
        panel.setMinSelectableDate(today);
        this.completedPercentage = completedPercentage;
        this.forwardObject = new RevocationDataInsertionResultObject();
    }

    @Override
    public Component getPanelComponent() {
        return panel;
    }

    @Override
    public boolean aboutToDisplayPanel() {
        if (getBackwardObject() != null && getBackwardObject() instanceof AuthorisingCapabilitySelectionResult)
            this.panel.setIssuer(
                    ((AuthorisingCapabilitySelectionResult)getBackwardObject()).getRevocationIssuer());
        return true;
    }

    @Override
    public void displayingPanel() {
        getWizard().setBackButtonEnabled(true);
        getWizard().setNextButtonEnabled(true);
        getWizard().setFinishButtonEnabled(false);
        getWizard().setCancelButtonEnabled(true);
        getWizard().setAccessRightsCreationPercentage(completedPercentage);
    }

    @Override
    public boolean aboutToHidePanel() {
        try {
            panel.validateForm();
            forwardObject.setCapabilityRevocation(this.createRevocationInstance());
            setForwardObject(forwardObject);
            return true;
        } catch (PanelRevocationDataException ex) {
            JOptionPane.showMessageDialog(getWizard(),
                    ex.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
            return false;
        }
    }

    private CapabilityRevocationType createRevocationInstance() throws PanelRevocationDataException {
        //FIXME this is a workaround till a Revocation Factory is defined
        CapabilityRevocationType rev = new ObjectFactory().createCapabilityRevocationType();
        
        rev.setVersion(ResourceBundle.getBundle("bundles/Version").getString("revocationSchema"));
        
        NameIDType issuer = new oasis.names.tc.saml._2_0.assertion.ObjectFactory().createNameIDType();
        issuer.setValue(panel.getIssuer());
        rev.setIssuer(issuer);
        
        ReturnReceiptTo notificationEmail = new ObjectFactory().createCapabilityRevocationTypeReturnReceiptTo();
        notificationEmail.setValue(panel.getNotificationEmail());
        rev.setReturnReceiptTo(notificationEmail);
        
        //Set the issue instant
        Date now = new Date();
        XMLGregorianCalendar issueIstant = null;
        try {
            issueIstant = CalendarUtils.newXmlGregorianCalendarFromDateAndTime(now, now);
        } catch (DatatypeConfigurationException ex) {
            throw new PanelRevocationDataException(ex.getMessage(), ex);
        }
        XMLGregorianCalendar issueIstantUTC = issueIstant.normalize();
        rev.setIssueInstant(issueIstantUTC);
        
        RevokedCapabilityData revData = new ObjectFactory().createCapabilityRevocationTypeRevokedCapabilityData();
        
        XMLGregorianCalendar revokedSince = null;
        try {
            revokedSince = CalendarUtils.newXmlGregorianCalendarFromDateAndTime(
                panel.getRevokedSinceDate(), panel.getRevokedSinceTime());
        } catch (DatatypeConfigurationException ex) {
            throw new PanelRevocationDataException(ex.getMessage(), ex);
        }
        revData.setRevokeSince(revokedSince);
        
        DependentTreeEffects revScope = new ObjectFactory()
            .createCapabilityRevocationTypeRevokedCapabilityDataDependentTreeEffects();
        if (panel.isRevScopeAllSelected()) {
            revScope.setAllCapabilities(new String());
        } else if (panel.isRevScopeOnlyDependantAuCapsSelected()) {
            revScope.setDependentCapabilitiesOnly(new String());
        } else if (panel.isRevScopeOnlySelectedAuCapSelected()) {
            revScope.setIdentifiedCapabilityOnly(new String());
        }
        revData.setDependentTreeEffects(revScope);
        
        revData.setReason(panel.getReason());
        
        RevokedCapabilityIdentifierType revokedAuCap = new ObjectFactory().createRevokedCapabilityIdentifierType();
        revokedAuCap.setAccessRightsCapabilityID(panel.getRevokedAuCapID());
        XMLGregorianCalendar revokedAuCapIssueDatetime = null;
        try {
            revokedAuCapIssueDatetime = CalendarUtils.newXmlGregorianCalendarFromDateAndTime(
                panel.getRevokedAuCapIssueDate(), panel.getRevokedAuCapIssueTime());
        } catch (DatatypeConfigurationException ex) {
            throw new PanelRevocationDataException(ex.getMessage(), ex);
        }
        revokedAuCap.setIssueInstant(revokedAuCapIssueDatetime);
        NameIDType revokedAuCapIssuer = new oasis.names.tc.saml._2_0.assertion.ObjectFactory().createNameIDType();
        revokedAuCapIssuer.setValue(panel.getRevokedAuCapIssuer());
        revokedAuCap.setIssuer(revokedAuCapIssuer);
        revokedAuCap.setVersion(panel.getRevokedAuCapVersion());
        revData.setRevokedCapability(revokedAuCap);
        
        rev.setRevokedCapabilityData(revData);
        
        rev.setIssuerAccessRightsCapability(
                ((AuthorisingCapabilitySelectionResult)getBackwardObject()).getAuthorisingCapability());
        
        try {
            rev.setRevocationID(IdentifierGenerator.generateIdentifier());
        } catch (NoSuchAlgorithmException e) {
            throw new PanelRevocationDataException(e.getMessage(), e);
        }
        
        return rev;
    }
}
